package com.example.java_gobang.game;

import com.example.java_gobang.JavaGobangApplication;
import com.example.java_gobang.model.User;
import com.example.java_gobang.model.UserMapper;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.ObjectMapper;
import org.apache.coyote.Response;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.socket.TextMessage;
import org.springframework.web.socket.WebSocketSession;

import java.io.IOException;
import java.util.UUID;

//两人对战的游戏房间
public class Room {
    private String roomId;//用String类型，方便下面  UUID  生成唯一值
    private User user1;
    private User user2;
    private int whiteUser;
    //用二维数组表示棋盘
    private int[][] board = new int[15][15];
    private ObjectMapper objectMapper = new ObjectMapper();

  //  @Autowired
    private OnlineUserManager onlineUserManager;
   // @Autowired
    private RoomManager roomManager;
    private UserMapper userMapper;

    public int getWhiteUser() {
        return whiteUser;
    }

    public void setWhiteUser(int whiteUser) {
        this.whiteUser = whiteUser;
    }

    public String getRoomId() {
        return roomId;
    }

    public void setRoomId(String roomId) {
        this.roomId = roomId;
    }

    public User getUser1() {
        return user1;
    }

    public void setUser1(User user1) {
        this.user1 = user1;
    }

    public User getUser2() {
        return user2;
    }

    public void setUser2(User user2) {
        this.user2 = user2;
    }

    public Room(){
        //生成唯一的房间Id
        roomId = UUID.randomUUID().toString();
        //通过JavaGobangApplication中记录的context手动获取前面的RoomManager和OnlineUserManager
        onlineUserManager = JavaGobangApplication.context.getBean(OnlineUserManager.class);
        roomManager = JavaGobangApplication.context.getBean(RoomManager.class);
        userMapper = JavaGobangApplication.context.getBean(UserMapper.class);
    }

    //处理一次落子操作
    public void putChess(String reqJson) throws IOException {
        //记录当前落子的位置
        GameRequest request = objectMapper.readValue(reqJson,GameRequest.class);
        GameResponse response = new GameResponse();
        //判断哪个玩家落的子
        int chess = request.getUserId() == user1.getUserId() ? 1:2;
        int row = request.getRow();
        int col = request.getCol();
        // 在客户端对 重复落子 已经进行过判断了，稳妥起见，服务器处再次判定
        if (board[row][col] != 0){
            System.out.println("当前位置 ("+row+","+col+"已经落子过了");
            return;
        }
        board[row][col] = chess;
        //打印棋盘落子信息
        printBoard();
        //进行胜负判定
        int winner = checkWinner(row,col,chess);
        //给(所有的)客户端返回响应
        response.setMessage("putChess");
        response.setUserId(request.getUserId());
        response.setRow(row);
        response.setCol(col);
        response.setWinner(winner);
        WebSocketSession session1 = onlineUserManager.getFromGameRoom(user1.getUserId());
        WebSocketSession session2 = onlineUserManager.getFromGameRoom(user2.getUserId());
        // 处理玩家掉线的情况
        if (session1 == null){
            response.setWinner(user2.getUserId());
            System.out.println("玩家1掉线");
        }
        if (session2 == null){
            response.setWinner(user1.getUserId());
            System.out.println("玩家2掉线");
        }
        String respJson = objectMapper.writeValueAsString(response);
        if (session1 != null){
            session1.sendMessage(new TextMessage(respJson));
        }
        if (session2 != null){
            session2.sendMessage(new TextMessage(respJson));
        }
        //如果玩家胜负已分, 就把 room 从管理器中销毁
        if (response.getWinner() != 0) {
            System.out.println("游戏结束, 房间已经销毁! roomId: " + roomId + " 获胜的为: " + response.getWinner());
            //更新获胜方，失败方
            int winUserId = response.getWinner();
            int loseUserId = response.getWinner() == user1.getUserId() ?user2.getUserId() : user1.getUserId();
            userMapper.userWin(winUserId);
            userMapper.userWin(loseUserId);
            roomManager.remove(roomId, user1.getUserId(), user2.getUserId());

        }


    }

    private void printBoard() {
        System.out.println("[打印棋盘信息]");
        System.out.println("=========================================================");
        for (int r=0;r< 15;r++){
            for (int c=0;c<15;c++){
                System.out.print(board[r][c] + " ");
            }
            //换行
            System.out.println();
        }
        System.out.println("=========================================================");
    }

    private int checkWinner(int row, int col,int chess) {
        //检查所有行
        for (int c=col-4;c<=col;c++){
            try {
                if (board[row][c] == chess
                        && board[row][c+1] == chess
                        && board[row][c+2] == chess
                        && board[row][c+3] == chess
                        && board[row][c+4] == chess
                ){
                    //五子连珠
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                //处理数组下标越界
                continue;
            }

        }
        //检查所有列
        for (int r=row-4;r<=row;r++){
            try {
                if (board[r][col] == chess
                        && board[r+1][col] == chess
                        && board[r+2][col] == chess
                        && board[r+3][col] == chess
                        && board[r+4][col] == chess
                ){
                    //五子连珠
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                //处理数组下标越界
                continue;
            }

        }
        //检查左对角线
        for (int c=col-4,r=row-4;c<=col && r<=row;c++,r++){
            try {
                if (board[r][c] == chess
                        && board[r+1][c+1] == chess
                        && board[r+2][c+2] == chess
                        && board[r+3][c+3] == chess
                        && board[r+4][c+4] == chess
                ){
                    //五子连珠
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                //处理数组下标越界
                continue;
            }

        }
        //检查右对角线
        for (int c=col+4,r=row-4;c>=col && r<=row;c--,r++){
            try {
                if (board[row][c] == chess
                        && board[r+1][c-1] == chess
                        && board[r+2][c-2] == chess
                        && board[r+3][c-3] == chess
                        && board[r+4][c-4] == chess
                ){
                    //五子连珠
                    return chess == 1 ? user1.getUserId() : user2.getUserId();
                }
            }catch (ArrayIndexOutOfBoundsException e){
                //处理数组下标越界
                continue;
            }

        }

        //胜负未分
        return 0;

    }
}
